home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
music
/
musgfa.zoo
/
makdosnd.lst
next >
Wrap
File List
|
1992-12-24
|
14KB
|
440 lines
' makdsnd.gfa 12 July 1991 modified 5 July 1992
' This program converts a *.tun file into a file of data which
' can be run by dosound (~xbios(32,L:...)). Pressing any key on
' the keyboard will interrupt the conversion and cause the data to
' be written out. The name of the output file is sound.dat
' programmed by Seymour Shlien in GFA Basic 3.5 on my 1040STE
' 624 Courtenay Avenue / Ottawa, Ontario, Canada K2A 3B5
' The program is public domain and not for commercial use.
DIM notes_to_microbeats%(12) ! duration code (1 - 12) to microbeat value
DIM elapsed_microbeats%(3) !number of microbeats for each voice (bar lines)
DIM seq%(3) !note sequence number in each voice during play
DIM micro_beat%(3) ! accumulated microbeats for voice (for play)
DIM next_event%(3) ! time for next note to sound for voice (for play)
DIM play_stop%(3) ! kounter for stop playing -used in cue
DIM note_tick%(3) ! time a note was sounded. Used for envelope
DIM tone_envel%(300) ! loudness envelope 1 to 100 for each voice
DIM voice_end_flag%(3) ! flag to signal end of voice
DIM note%(3),duration%(3),draw_flag%(3) !last notes sounded
DIM kount%(2),vclen%(2),repeat_sign%(2),repeat_count%(2)
REM memory for storing music
DIM tnote&(2,1000),mubeat%(3)
DIM last_note_duration%(3) !need it if we correct an error with right button
DIM music_mem&(40000)
DIM music_cmp&(5000)
DIM volum(3),decay(3)
DEFMOUSE 0
CLS
voic%=1
voic1%=voic%-1
volum(0)=14
volum(1)=13
volum(2)=12
decay(0)=0.08
decay(1)=0.09
decay(2)=0.13
PRINT "This program converts a *.tun file"
PRINT "into an *.XBS file. Select the"
PRINT "desired file using the file"
PRINT "selector. The program converts this"
PRINT "file as it is playing it on the"
PRINT "Atari sound chip. It stops when it"
PRINT "plays the entire file or when"
PRINT "you hit the space bar. It then"
PRINT "records everything it played on"
PRINT "the file sound.xbs."
PRINT "... Hit space bar to continue."
DO UNTIL key_interrupt$<>""
key_interrupt$=INKEY$
LOOP
FOR i%=0 TO 2
offset=volum(i%)
attenuation=decay(i%)
@make_tone_envelope(i%,offset,attenuation)
NEXT i%
@read_music_data
@initialize_note_table
@read_tune_file
@play_tune
' @dosound
@write_sound
> PROCEDURE tnote_structure_doc
' tnote array stores the pitch and duration value of every note
' to be played for the three voices (tracks). The high byte contains
' the duration code and other special codes. The low byte contains
' the pitch code. The pitch code modulo 12 maps into the note letter
' c,c#,d,d#,... b. If the pitch code is zero then a rest is assumed.
' The duration code 0 to 12 map to note duration in the order that
' the note duration sprites appear in the menu. Other codes 13 to 15
' control repeats. Codes 16 and 17 are not fully implemented but allow
' the inclusion of long rests in a particular voice. Other codes are
' only used for the input /output files *.TUN for specifying key signature,
' time signature, and tempo.
RETURN
> PROCEDURE read_music_data
@read_timconv_array
RETURN
> PROCEDURE read_timconv_array
LOCAL i%
REM for converting notes to microbeats
FOR i%=0 TO 12
READ notes_to_microbeats%(i%)
NEXT i%
DATA 3,6,12,18,24,36,48,72,96,144,2,4,8
' whole note = 96 microbeats
RETURN
'
'
'
> PROCEDURE yamaha_doc
' I was not very successful using the sound or wave commands in gfa
' basic to produce polyphonic music. (Its ok for chords). Furthermore
' the envelope feature on the Yamaha chip produced problems that I could
' not resolve. I therefore implemented the sound at a fairly low level
' using BIOS commands. The following functions interface with the xbios
' command 28. This is tricky since some of the registers are used for
' disk i/o and damage to the disk can result. I put in extra protection
' in this code which should never be commented out.
' I decided to implement the music production this way rather than
' using the xbios 32 play sequence command so that I can follow the
' production of each note. Even though I am controlling the amplitude
' envelope every 50 th of a second, as well as placing sprites on the
' screen, there is ample time left over.
' The make_tone_envelope function controls the linear rise and two
' linear decay modes of the amplitude. The envelope is put into a table.
'
' The procedure play_next_notes, polls all three voices to see whether
' it is time to change the volume or pitch of a note. When it is
' time to change it finds the next note and sets the time to change
' that note based on the notes duration and the slowness of the music.
RETURN
> PROCEDURE initialize_note_table
' Thanks ken
LOCAL note|
IF NOT u__init!
u__init!=TRUE
DIM u__period%(96)
FOR note|=0 TO 12
FOR o%=0 TO 7
u__period%(12*o%+note|)=125000/(2^o%*440*(2^(note|/12))/(2^(10/12))/16)+0.5
NEXT o%
NEXT note|
ENDIF
RETURN
> PROCEDURE set_tone_period(voice%,period%)
LOCAL reg%,period_low%,period_hi%,reg_val%
IF voice%<0 OR voice%>2
GOTO set_tone_err
ENDIF
reg%=voice%*2
period_low%=AND(period%,255)
period_hi%=SHR(AND(period%,&HF00),8)
period%=XBIOS(28,period_low%,reg%+128) !period% is not used anymore
music_mem&(memptr%)=SHL(reg%,8)+period_low%
INC memptr%
reg%=reg%+1
reg_val%=AND(XBIOS(28,0,reg%),&HF0) !must save hi bits
reg_val%=OR(AND(period_hi%,15),reg_val%) !combine low and hi bits
reg_val%=XBIOS(28,reg_val%,reg%+128) !output
music_mem&(memptr%)=SHL(reg%,8)+reg_val%
INC memptr%
GOTO set_tone_return
set_tone_err:
STOP
set_tone_return:
RETURN
> PROCEDURE disable_noise_channels
LOCAL reg_val%
reg_val%=XBIOS(28,0,7)
reg_val%=OR(AND(reg_val%,192),56)
reg_val=XBIOS(28,reg_val%,7+128)
music_mem&(memptr%)=SHL(7,8)+reg_val%
INC memptr%
RETURN
> PROCEDURE set_volume(voice%,level%)
' level between 0 and 15 for constant volume
' level 16 for waveform envelope
LOCAL reg%,reg_val%
IF voice%<0 OR voice>2 !check for legal voice number
GOTO set_volume_err
ENDIF
IF level%>31 OR level%<0
GOTO set_volume_err
ENDIF
reg%=8+voice%
regval%=XBIOS(28,0,reg%)
regval%=AND(regval%,&HE0) !save only top 3 bits
regval%=OR(regval%,AND(level%,31))
regval%=XBIOS(28,regval%,reg%+128)
music_mem&(memptr%)=SHL&(reg%,8)+regval%
INC memptr%
GOTO set_volume_return
set_volume_err:
STOP
set_volume_return:
RETURN
> PROCEDURE dosound
LOCAL i%
' SPOKE &H484,PEEK(&H484) AND NOT 1
addr%=VARPTR(music_mem&(0))
PRINT addr%
FOR i%=0 TO 200
PRINT BYTE{addr%+i%};" ";
NEXT i%
~XBIOS(32,L:VARPTR(music_mem&(0)))
RETURN
> PROCEDURE write_sound
LOCAL addr%
addr%=VARPTR(music_mem&(0))
BSAVE "sound.xbs",addr%,memptr%*2
RETURN
> PROCEDURE make_tone_envelope(num%,offset,attenuation)
LOCAL index%,val%,i%
index%=num%*100
FOR i%=0 TO 99
val%=offset-i%*attenuation
val%=MAX(val%,0)
val%=MIN(val%,15)
tone_envel%(i%+index%)=val%
NEXT i%
RETURN
> PROCEDURE play_tune
' The procedure plays song number numb%.
' The base_time% is set to the current time in ticks.
' The function next_note is called repeatedly, to sound the next
' note when it is time to do so. If a note has been sounded, we
' draw it on the staff.
LOCAL i%,note_xposition%,k%
skoll%=0 ! rem scrolling is off
' find voices
IF speed%>0
slowness=135/speed% !comment this statement when debugging
ELSE
slowness=2
ENDIF
base_time%=TIMER
FOR i%=1 TO 3
seq%(i%)=0
repeat_count%(i%-1)=0
repeat_sign%(i%-1)=0
play_stop%(i%-1)=vclen%(i%-1)
elapsed_microbeats%(i%-1)=0
micro_beat%(i%)=0
next_bar_line%=bar_length%
next_event%(i%)=base_time%+slowness*micro_beat%(i%)
IF seq%(i%)<=play_stop%(i%-1)
voice_end_flag%(i%)=0
ELSE
voice_end_flag%(i%)=1
ENDIF
@set_volume(i%-1,10)
@set_tone_period(i%-1,5)
NEXT i%
memptr%=0
k%=0
'
' ready to start
@disable_noise_channels
REPEAT
@play_next_notes
' the r